# -*- coding:utf-8 -*-

import os
import sys
from inspect import getmembers
from inspect import isclass

import six
from flask import jsonify
from flask import send_file
from flask_restful import Resource

from api.lib.perm.auth import auth_required


# 抽象一个公共的API接口试图，类似于Java中的BaseControler.java
class APIView(Resource):
    method_decorators = [auth_required]

    def __init__(self):
        super(APIView, self).__init__()

    # 装饰器标记为静态方法，不需要实例化类即可调用，如APIView.jsonify(...)
    # 返回json格式的响应
    @staticmethod
    def jsonify(*args, **kwargs):
        return jsonify(*args, **kwargs)

    # 发送附件给客户端，类似前端下载文件
    @staticmethod
    def send_file(*args, **kwargs):
        return send_file(*args, **kwargs)

# 获取当前文件目录的绝对路径
API_PACKAGE = os.path.abspath(os.path.dirname(__file__))


# 作用：注册当前蓝图下的所有资源（接口），这里对应的是acl、cmdb、common_setting目录
# 参数1：resource_path：根据resource_path定义，注册resource_path指定目录下所有的Resoure资源（其实就是接口）
# 参数2：rest_api：当前的flask-restul的Api实例，蓝图需要传递到Api对象中
def register_resources(resource_path, rest_api):
    # 元组（文件夹路径, 文件夹名字, 文件名）
    for root, _, files in os.walk(os.path.join(resource_path)):
        for filename in files:
            if not filename.startswith("_") and filename.endswith("py"):
                if root not in sys.path:
                    sys.path.insert(1, root)
                view = __import__(os.path.splitext(filename)[0])

                # 判断对象是类并且是Resource的子类, 一个文件模块里面有多个类
                # arr[] = getmembers(obj)以(k,v)的形式返回obj对象里面所有的元素，定义的类、变量、导入包之类的
                resource_list = [o[0] for o in getmembers(view) if isclass(o[1]) and issubclass(o[1], Resource)]
                
                # 排除掉APIView，因为APIView是定义的父类, 最终留下的是文件中的各种View对象, 比如acl.app.py为['AppAccessTokenView', 'AppView']
                resource_list = [i for i in resource_list if i != "APIView"]
         
                # 遍历处理每一个具体的资源类，即抽象的Resource类
                for resource_cls_name in resource_list:
                    # 获取View实体对象中的某个类对象
                    resource_cls = getattr(view, resource_cls_name)

                    if not hasattr(resource_cls, "url_prefix"):
                        resource_cls.url_prefix = ("",)
                    if isinstance(resource_cls.url_prefix, six.string_types):
                        resource_cls.url_prefix = (resource_cls.url_prefix,)

                    # resource_cls为视图对象，即为flask-restful的Resource的子类，这里需要注册到Api里面
                    rest_api.add_resource(resource_cls, *resource_cls.url_prefix)

